package 方法句柄;

/*public MethodHandle findVirtual​(类<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
【虚方法是可被子类重写的方法】
生成虚方法的方法句柄。 方法句柄的类型将是方法的类型，前缀为接收器类型（通常为refc ）。 查找对象必须可以访问该方法及其所有参数类型。
调用时，句柄将第一个参数视为接收者，对于非私有方法，调度接收者的类型以确定要输入的方法实现。 对于私有方法，将在接收器上调用refc的命名方法。 （调度操作与invokevirtual或invokeinterface指令执行的操作相同。）

如果查找类具有访问该成员的完全权限，则第一个参数的类型为refc 。 否则，该成员必须为protected并且第一个参数的类型将限制为查找类。

当且仅当设置了方法的变量arity修饰符位（ 0x0080 ）时，返回的方法句柄将具有variable arity 。

因为一般equivalence之间invokevirtual的指令和方法所生产手柄findVirtual ，如果类是MethodHandle和名称的字符串是invokeExact或invoke ，所得方法手柄等效于一个由产生MethodHandles.exactInvoker或MethodHandles.invoker具有相同type参数。

如果类为VarHandle且名称字符串对应于签名多态访问模式方法的名称，则生成的方法句柄等效于MethodHandles.varHandleInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType)生成的方法句柄，其访问模式对应于名称字符串且具有相同的type参数。
参数：
refc - 从中访问方法的类或接口
name - 方法的名称
type - 方法的类型，省略receiver参数

结果：所需的方法句柄

异常：
NoSuchMethodException - 如果该方法不存在
IllegalAccessException - 如果访问检查失败，或者方法是 static ，或者方法的变量arity修饰符位已设置且 asVarargsCollector失败
SecurityException - 如果存在安全管理器且 refuses access
NullPointerException - 如果任何参数为null
例：
*/

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
import static org.junit.Assert.assertEquals;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import org.junit.jupiter.api.Test;
public class findVirtual用法 {
	public static void main(String[] args) throws Throwable {
		MethodHandle MH_concat = publicLookup().findVirtual(String.class,"concat", methodType(String.class,String.class));
		MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,"hashCode", methodType(int.class));
		MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,"hashCode", methodType(int.class));
		System.out.println((String) MH_concat.invokeExact("xx", "y"));//xxy
		System.out.println((int) MH_hashCode.invokeExact((Object)"xy"));//3841
		System.out.println((int) MH_hashCode_String.invokeExact("xy"));//3841
		// interface method:
		MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,"subSequence", methodType(CharSequence.class, int.class, int.class));
		System.out.println(MH_subSequence.invoke("abcdefghi", 3, 6).toString());//def
		// constructor "internal method" must be accessed differently:
		MethodType MT_newString = MethodType.methodType(void.class); //()V for new String()
		try {  
			System.out.println(lookup().findVirtual(String.class, "<init>", MT_newString));
		 } catch (NoSuchMethodException ex) {System.out.println("impossible"); } // OK
		MethodHandle MH_newString = publicLookup().findConstructor(String.class, MT_newString);
		System.out.println("-----"+(String) MH_newString.invokeExact());
	}
}

